
// Copyright (c) 2002 HTHK
package com.ffpc.util;

public class FtpClient
{
  // FTP dual sockets
  java.net.Socket controlSocket = null;
  java.net.ServerSocket dataSocket = null;

  // Used to communicate over control socket
  java.io.BufferedReader controlIn = null;
  java.io.PrintWriter controlOut = null;

  // Used for receiving files from server
  java.io.RandomAccessFile fin = null;
  java.io.DataInputStream dis = null;
  java.net.Socket dataOut = null;

  // Used for sending files to server
  java.io.InputStream is = null;
  java.io.DataOutputStream dos = null;
  java.net.Socket dataIn = null;

  String hostName = null;
  String userName = null;
  String passWord = null;
  int transferMode = ASCII_MODE;
  String transferFile = null;
  String serverDirectory = null;
  String clientDirectory = null;

  public static final int BINARY_MODE=0;
  public static final int ASCII_MODE=1;


  public FtpClient(String hN,String uN,String pW)
  {
    hostName=hN;userName=uN;passWord=pW;
    this.connect();
  }

  private void connect()
  {
    try
    {
      //ftp has a dual-socket protocol
      controlSocket = new java.net.Socket(hostName,21);
      controlSocket.setSoTimeout(1000);
      dataSocket = new java.net.ServerSocket(0);
      dataSocket.setSoTimeout(1000);

      // the control channel (messages to ftp server)
      controlOut= (new java.io.PrintWriter(controlSocket.getOutputStream(),true));

      // the control channel (messages from ftp server)
      controlIn= (new java.io.BufferedReader(new java.io.InputStreamReader(controlSocket.getInputStream())));

      // Login to the server
      controlOut.println("USER " +userName);
      controlOut.flush();
      controlOut.println("PASS " +passWord);
      controlOut.flush();
    }
    catch(java.net.UnknownHostException e)
    {
      e.printStackTrace();
    }
    catch (java.io.IOException e)
    {
      e.printStackTrace();
    }
  }

  public void setMode(int tM)
  {
    transferMode=tM;
  }

  public void setFile(String f)
  {
    transferFile=f;
  }

  public void setServerDir(String sD)
  {
    serverDirectory=sD;
  }

  public void setClientDir(String cD)
  {
    clientDirectory=cD;
  }

  private void setTransferMode()
  {
    // Set type of transfer ASCII or BINARY
    if(transferMode==FtpClient.BINARY_MODE)
    {
      //controlOut.println("TYPE L 32"); //BINARY {to unix}
      //controlOut.println("TYPE L 8"); //BINARY {to pc}
      controlOut.println("TYPE I"); //BINARY
    }
    else
    {
      //controlOut.println("TYPE A N"); //ASCII
      controlOut.println("TYPE A"); //ASCII
    }
    controlOut.flush();
  }

  private void setClientPort()
  {
    // Determine which port to send/get data to/from
    // must put port info into the ftp RFC 959 format
    // PORT h1,h2,h3,h4,p1,p2
    int clientPort = dataSocket.getLocalPort();
    int p1 = ((clientPort & 0xff00) >> 8);
    int p2 = (clientPort & 0x00ff);
    String port_command = "PORT " +
                          controlSocket.getLocalAddress().getHostAddress().replace('.',',')+ //h1,h2,h3,h4
                          "," + p1 + "," + p2; //p1,p2
    controlOut.println(port_command);
    controlOut.flush();
  }

  private void setServerDirectory()
  {
    // go to proper directory on server side
    if (serverDirectory != null)
    {
      controlOut.println("CWD " + serverDirectory);
      controlOut.flush();
    }
  }

  private void createClientSideFile()
  {
    // create file structure (on client-side) of the file you will retrieve
    // we will write to this file on the client local disk
    try
    {
      if (clientDirectory != null)
        fin=new java.io.RandomAccessFile((clientDirectory+transferFile),"rw");
      else
        fin=new java.io.RandomAccessFile((transferFile),"rw");
    }
    catch (java.io.FileNotFoundException e)
    {
      e.printStackTrace();
    }
    catch (java.io.IOException e){
      e.printStackTrace();
    }
  }

  private void setClientSideFile()
  {
    // create file structure (on client-side) of the file you will retrieve
    // we will write to this file on the client local disk
    try
    {
      // do put logic
      if (clientDirectory != null)
        is = new java.io.FileInputStream(clientDirectory+transferFile);
      else
        is = new java.io.FileInputStream(transferFile);
    }
    catch (java.io.FileNotFoundException e)
    {
      e.printStackTrace();
    }
    catch(java.io.IOException e)
    {
      e.printStackTrace();
    }
  }

  public boolean getFile()
  {
    try
    {
      this.setTransferMode();
      this.setClientPort();
      this.setServerDirectory();
      this.createClientSideFile();

      // request (from server) to retrive a file
      controlOut.println("RETR " +transferFile);
      controlOut.flush();

      // retrive the file from the data socket
      dataIn=dataSocket.accept();
      dis =new java.io.DataInputStream(dataIn.getInputStream());

      // read info from dataSocket & write out to local disk
      int offset;
      byte[] data = new byte[1024];
      while((offset=dis.read(data))!=-1)
      {
        fin.write(data, 0, offset);
      }
      fin.close();
      dis.close();
      dataIn.close();
      //this.showControlReponses();
    }
    catch (java.net.UnknownHostException e)
    {
      return false;
    }
    catch (java.io.IOException e)
    {
      return false;
    }
    return true;
  }

  public boolean putFile()
  {
    try
    {
      this.setTransferMode();
      this.setClientPort();
      this.setServerDirectory();
      this.setClientSideFile();

      // request (from server) to retrive a file
      controlOut.println("STOR " +transferFile);
      controlOut.flush();

      // store the file to the data socket
      dataOut=dataSocket.accept();
      dos = new java.io.DataOutputStream(dataOut.getOutputStream());

      // write info from local disk & write out to dataSocket
      int offset;
      byte[] data = new byte[1024];
      while ((offset=is.read(data))!=-1)
      {
        dos.write(data, 0, offset);
      }
      is.close();
      dos.close();
      dataOut.close();

      //this.showControlReponses();
    }
    catch (java.net.UnknownHostException e)
    {
      e.printStackTrace();
      return false;
    }
    catch (java.io.IOException e)
    {
      e.printStackTrace();
      return false;
    }
    catch (Exception e)
    {
      e.printStackTrace();
      return false;
    }
    return true;
  }

  public void bye()
  {
    quitFtp();
  }

  private void quitFtp()
  {
    try
    {
      // quit the ftp session
      controlOut.println("QUIT");
      controlOut.flush();

      // Get a history of all processing
      this.showControlReponses();
      controlOut.close();
      controlIn.close();
      controlSocket.close();
      dataSocket.close();
    }
    catch (java.io.IOException e)
    {
      e.printStackTrace();
    }
  }

  private void showControlReponses()
  {
    try
    {
      // Display history of the ftp servers responses
      // to our commands
      String inputLine_client;
      while ((inputLine_client=controlIn.readLine())!=null)
      {
        //System.out.println(inputLine_client);
      }  
    }
    catch (java.io.IOException e)
    {
      e.printStackTrace();
    }
  }
}
 